package com.ruoyi.labdata.service.impl;

import com.alibaba.fastjson.JSON;
import com.ruoyi.labdata.domain.ChooseDataVo;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import com.ruoyi.labdata.domain.LabFlowInstance;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.course.domain.LabCourse;
import com.ruoyi.course.domain.LabCourseDate;
import com.ruoyi.course.domain.LabCourseTimetable;
import com.ruoyi.course.mapper.LabCourseDateMapper;
import com.ruoyi.course.service.ILabCourseTimetableService;
import com.ruoyi.labdata.domain.LabFile;
import com.ruoyi.labdata.domain.LabReservation;
import com.ruoyi.labdata.domain.LabReservationParameterPersonnel;
import com.ruoyi.labdata.mapper.LabHolidayReservationMapper;
import com.ruoyi.labdata.mapper.LabReservationMapper;
import com.ruoyi.labdata.service.ILabFileService;
import com.ruoyi.labdata.service.ILabFlowInstanceService;
import com.ruoyi.labdata.service.ILabHolidayReservationService;
import com.ruoyi.labdata.service.ILabReservationParameterPersonnelService;
import com.ruoyi.labdata.service.ILabReservationService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.utils.FileTypeEnum;
import com.ruoyi.system.utils.SysDateUtils;
import com.ruoyi.wechatapi.domain.QueryEntity;

import cn.hutool.core.util.ObjectUtil;

/**
 * 实验室预约Service业务层处理
 * 
 * @author ruoyi
 * @date 2022-03-27
 */
@Service
public class LabReservationServiceImpl implements ILabReservationService {
	private static final String belongType = FileTypeEnum.LabReservation.getValue();;

	@Resource
	private LabReservationMapper labReservationMapper;

	@Autowired
	private ILabFileService labFileService;

	@Autowired
	private ISysUserService sysUserService;

	@Autowired
	private ILabFlowInstanceService labFlowInstanceService;

	@Autowired
	private ILabReservationParameterPersonnelService labReservationParameterPersonnelService;

	@Resource
	private LabHolidayReservationMapper labHolidayReservationMapper;
	@Autowired
	private ILabHolidayReservationService reservationService;
	
	@Autowired
	private ILabCourseTimetableService labCourseTimetableService;
	
	@Autowired
	private LabCourseDateMapper labCourseDateMapper;

	/**
	 * 查询实验室预约
	 * 
	 * @param instanceId
	 *            实验室预约ID
	 * @return 实验室预约
	 */
	@Override
	public LabReservation selectLabReservationById(Long instanceId) {
		List<LabFile> labFiles = labFileService.getFiles(instanceId, belongType);
		LabReservation labReservation = labReservationMapper.selectLabReservationById(instanceId);
		// if (ObjectUtil.isNull(labReservation)){
		// throw new
		// RuntimeException("此实验室在此预约时间点未生成实验室可预约配置,不能进行预约，请先生成实验室预约配置");
		// }
		labReservation.setImages(labFiles);
		// 查询预约
		LabReservationParameterPersonnel labReservationParameterPersonnel = new LabReservationParameterPersonnel();
		labReservationParameterPersonnel.setLabReservationId(instanceId);
		labReservationParameterPersonnel.setType("0");
		List<LabReservationParameterPersonnel> appointmentList = labReservationParameterPersonnelService
				.selectLabReservationParameterPersonnelList(labReservationParameterPersonnel);
		labReservation.setAppointmentList(appointmentList);
		// 参与人员
		LabReservationParameterPersonnel labReservationParameterPersonnel2 = new LabReservationParameterPersonnel();
		labReservationParameterPersonnel2.setLabReservationId(instanceId);
		labReservationParameterPersonnel2.setType("1");
		List<LabReservationParameterPersonnel> participationList = labReservationParameterPersonnelService
				.selectLabReservationParameterPersonnelList(labReservationParameterPersonnel2);
		labReservation.setParticipationList(participationList);
		return labReservation;
	}

	/**
	 * 查询实验室预约列表
	 * 
	 * @param labReservation
	 *            实验室预约
	 * @return 实验室预约
	 */
	@Override
	public List<LabReservation> selectLabReservationList(LabReservation labReservation) {
		SysUser loginUser = SecurityUtils.getLoginUser().getUser();
		labReservation.setCreateBy(loginUser.getUserName());
		return labReservationMapper.selectLabReservationList(labReservation);
	}

	/**
	 * 新增实验室预约
	 * 
	 * @param labReservation
	 *            实验室预约
	 * @return 结果
	 */
	@Override
	@Transactional
	public int insertLabReservation(LabReservation labReservation) {
		
		LabCourse labCourse = getCourseParam(labReservation);
		reservationService.doReservation(labCourse);
		//List<ChooseDataVo> chooseDataVos = checkReservation(labReservation);
		SysUser user = sysUserService.selectUserByUserName(labReservation.getCreateBy());
		labReservation.setCreateTime(DateUtils.getNowDate());
		labReservation.setCreateUserId(user.getUserId());
		labReservation.setCreateOrgId(user.getDeptId());
		labReservation.setCreateTime(new Date());
		// 保存流程信息
		labFlowInstanceService.insertLabFlowInstance(labReservation);
		labFileService.insertFiles(labReservation.getImages(), labReservation.getInstanceId(), belongType);
		// 保存参与人员信息
		List<LabReservationParameterPersonnel> appointmentList = labReservation.getAppointmentList();
		List<LabReservationParameterPersonnel> participationList = labReservation.getParticipationList();
		ArrayList<LabReservationParameterPersonnel> labReservationParameterPersonnelAll = new ArrayList<>();
		labReservationParameterPersonnelAll.addAll(appointmentList);
		labReservationParameterPersonnelAll.addAll(participationList);
		for (LabReservationParameterPersonnel labReservationParameterPersonnel : labReservationParameterPersonnelAll) {
			labReservationParameterPersonnel.setLabReservationId(labReservation.getInstanceId());
			labReservationParameterPersonnelService
					.insertLabReservationParameterPersonnel(labReservationParameterPersonnel);
		}
		insertCourseDate(labReservation, labCourse);
		return labReservationMapper.insertLabReservation(labReservation);
	}

	private List<ChooseDataVo> checkReservation(LabReservation labReservation) {
		String chooseData = labReservation.getChooseData();
		List<ChooseDataVo> chooseDatas = JSON.parseArray(chooseData, ChooseDataVo.class);

		StringBuffer totalErro = new StringBuffer();
		for (ChooseDataVo data : chooseDatas) {
			String holidayDate = data.getHolidayDate();
			LabCourseDate query = new LabCourseDate();
			query.setCourseDate(DateUtils.parseDate(holidayDate));
			List<LabCourseDate> labCourseDates = this.labCourseDateMapper.selectLabCourseDateList(query);

			StringBuffer erroInfo = new StringBuffer();
			if (CollectionUtils.isNotEmpty(labCourseDates)) {
				for (LabCourseDate labCourseDate : labCourseDates) {
					if (labReservation.getInstanceId() != null && labCourseDate.getAppointId().longValue() == labReservation.getInstanceId().longValue()) {
						continue;
					}
					Integer section = labCourseDate.getSectionStart();
					switch (section) {
						case 1:
							if (data.getSectionOne() != null && data.getSectionOne().intValue() == 1) {
								erroInfo.append(section).append(",");
							}
							break;
						case 2:
							if (data.getSectionTwo() != null && data.getSectionTwo().intValue() == 1) {
								erroInfo.append(section).append(",");
							}
							break;
						case 3:
							if (data.getSectionThree() != null && data.getSectionThree().intValue() == 1) {
								erroInfo.append(section).append(",");
							}
							break;
						case 4:
							if (data.getSectionFour() != null && data.getSectionFour().intValue() == 1) {
								erroInfo.append(section).append(",");
							}
							break;
						case 5:
							if (data.getSectionFive() != null && data.getSectionFive().intValue() == 1) {
								erroInfo.append(section).append(",");
							}
							break;
						case 6:
							if (data.getSectionSix() != null && data.getSectionSix().intValue() == 1) {
								erroInfo.append(section).append(",");
							}
							break;
						case 7:
							if (data.getSectionSeven() != null && data.getSectionSeven().intValue() == 1) {
								erroInfo.append(section).append(",");
							}
							break;
						case 8:
							if (data.getSectionEight() != null && data.getSectionEight().intValue() == 1) {
								erroInfo.append(section).append(",");
							}
							break;
						case 9:
							if (data.getSectionNine() != null && data.getSectionNine().intValue() == 1) {
								erroInfo.append(section).append(",");
							}
							break;
						case 10:
							if (data.getSectionTen() != null && data.getSectionTen().intValue() == 1) {
								erroInfo.append(section).append(",");
							}
							break;
						case 11:
							if (data.getSectionEleven() != null && data.getSectionEleven().intValue() == 1) {
								erroInfo.append(section).append(",");
							}
							break;
						case 12:
							if (data.getSectionTwelve() != null && data.getSectionTwelve().intValue() == 1) {
								erroInfo.append(section).append(",");
							}
							break;
					}
				}
			}
			if (erroInfo.length()> 0) {
				totalErro.append("日期：").append(holidayDate).append("节次：").append(erroInfo).append(";");
			}
			data.buildSectionList(); // 构建节次列表
		}
		if (totalErro.length() > 0) {
			throw new RuntimeException("错误：实验室已经被预定过,预定信息，" + totalErro);
		}
		return chooseDatas;
	}

	private LabCourse getCourseParam(LabReservation labReservation) {
		
		LabCourse labCourse = new LabCourse();
		//labCourse.setSectionEnd(labReservation.getSectionEnd());
		//labCourse.setSectionStart(labReservation.getSectionStart());
		labCourse.setLabId(labReservation.getClassRoomId());
		//labCourse.setWeekEnd(labReservation.getWeekEnd());
		//labCourse.setWeekStart(labReservation.getWeekStart());
		LabCourseTimetable timetable = labCourseTimetableService.getDefaultTimetable(new Date());
		if(timetable==null){
			throw new RuntimeException("本学期日历尚未设置.请到课程管理中先设置学期日历.");
		}
		/*int maxNum = SysDateUtils.getCourseWeekNum(timetable.getCourseStartDate(), timetable.getLastDate());
		if(labReservation.getWeekEnd()>maxNum){
			throw new RuntimeException("结束周次已经超出本学期范围");
		}*/

		labCourse.setTimetableId(timetable.getTimetableId());
		//labCourse.setWeekDayOpt(labReservation.getWeekDayOpt());
		List<LabCourseDate> dates = new ArrayList<LabCourseDate>();
		String chooseData = labReservation.getChooseData();
		List<ChooseDataVo> chooseDatas = JSON.parseArray(chooseData, ChooseDataVo.class);
		if(chooseDatas!=null && chooseDatas.size()>0){
			for(ChooseDataVo data : chooseDatas){
				LabCourseDate labCourseDate = new LabCourseDate();
				labCourseDate.setCourseDate(DateUtils.parseDate(data.getHolidayDate()));
				labCourseDate.setTimetableId(timetable.getTimetableId());
				labCourseDate.setWeekNum(SysDateUtils.getCourseWeekNum(timetable.getCourseStartDate(),labCourseDate.getCourseDate()));
				List<Integer> sectionList = new ArrayList<Integer>();
				if (data.getSectionOne() != null && data.getSectionOne().intValue() == 1) {
					sectionList.add(1);
				}
				if (data.getSectionTwo() != null && data.getSectionTwo().intValue() == 1) {
					sectionList.add(2);
				}
				if (data.getSectionThree() != null && data.getSectionThree().intValue() == 1) {
					sectionList.add(3);
				}
				if (data.getSectionFour() != null && data.getSectionFour().intValue() == 1) {
					sectionList.add(4);
				}
				if (data.getSectionFive() != null && data.getSectionFive().intValue() == 1) {
					sectionList.add(5);
				}
				if (data.getSectionSix() != null && data.getSectionSix().intValue() == 1) {
					sectionList.add(6);
				}
				if (data.getSectionSeven() != null && data.getSectionSeven().intValue() == 1) {
					sectionList.add(7);
				}
				if (data.getSectionEight() != null && data.getSectionEight().intValue() == 1) {
					sectionList.add(8);
				}
				if (data.getSectionNine() != null && data.getSectionNine().intValue() == 1) {
					sectionList.add(9);
				}
				if (data.getSectionTen() != null && data.getSectionTen().intValue() == 1) {
					sectionList.add(10);
				}
				if (data.getSectionEleven() != null && data.getSectionEleven().intValue() == 1) {
					sectionList.add(11);
				}
				if (data.getSectionTwelve() != null && data.getSectionTwelve().intValue() == 1) {
					sectionList.add(12);
				}
				labCourseDate.setSectionList(sectionList);
				StringBuffer remark = new StringBuffer();
				for(Integer i : sectionList){
					if(remark.length()>0){
						remark.append(",");
					}
					remark.append(i);
				}
				labCourseDate.setRemark(remark+" 节");
				dates.add(labCourseDate);
				
			}
		}
		labCourse.setCourseDateList(dates);
		return labCourse;
	}


	/**
	 * 修改实验室预约
	 * 
	 * @param labReservation
	 *            实验室预约
	 * @return 结果
	 */
	@Override
	@Transactional
	public int updateLabReservation(LabReservation labReservation) {
		//取消之前的预定
		LabReservation oldLabReservation = labReservationMapper.selectLabReservationById(labReservation.getInstanceId());
		LabCourse oldlabCourse = getCourseParam(oldLabReservation);
		reservationService.cancelReservation(oldlabCourse);

		//执行需要更新的预定
		LabCourse labCourse = getCourseParam(labReservation);
		reservationService.doReservation(labCourse);
		//List<ChooseDataVo> chooseDataVos = checkReservation(labReservation);
		SysUser user = sysUserService.selectUserByUserName(labReservation.getCreateBy());
		labReservation.setCreateOrgId(user.getDeptId());
		labFlowInstanceService.updateLabFlowInstance(labReservation);
		labFileService.updateFiles(labReservation.getImages(), labReservation.getInstanceId(), belongType);
		// 保存参与人员信息
		Long[] longs1 = new Long[1];
		longs1[0] = labReservation.getInstanceId();
		labReservationParameterPersonnelService.deleteLabReservationParameterPersonnelByLabReservationId(longs1);
		List<LabReservationParameterPersonnel> appointmentList = labReservation.getAppointmentList();
		List<LabReservationParameterPersonnel> participationList = labReservation.getParticipationList();
		ArrayList<LabReservationParameterPersonnel> labReservationParameterPersonnelAll = new ArrayList<>();
		labReservationParameterPersonnelAll.addAll(appointmentList);
		labReservationParameterPersonnelAll.addAll(participationList);
		for (LabReservationParameterPersonnel labReservationParameterPersonnel : labReservationParameterPersonnelAll) {
			labReservationParameterPersonnel.setLabReservationId(labReservation.getInstanceId());
			labReservationParameterPersonnelService
					.insertLabReservationParameterPersonnel(labReservationParameterPersonnel);
		}
		insertCourseDate(labReservation, labCourse);
		return labReservationMapper.updateLabReservation(labReservation);
	}

	@Override
	@Transactional
	public int updateLabReservationStatus(LabReservation labReservation) {
		//如果拒绝，取消预定
		LabFlowInstance labFlowInstance = labFlowInstanceService.selectLabFlowInstanceById(labReservation.getInstanceId());
		if(labFlowInstance.getFlowStatusOpt().equals("refused")){
			LabCourse labCourse = getCourseParam(labReservation);
			reservationService.cancelReservation(labCourse);
			labCourseDateMapper.deleteLabCourseDateByAppointId(labReservation.getInstanceId());
		}
		return labReservationMapper.updateLabReservation(labReservation);
	}
	
	private void insertCourseDate(LabReservation labReservation, LabCourse labCourse) {
		Long appointId = labReservation.getInstanceId();
		labCourseDateMapper.deleteLabCourseDateByAppointId(appointId);
		for (LabCourseDate courseDate : labCourse.getCourseDateList()) {
			//courseDate.setSectionStart(section);
			courseDate.setAppointId(appointId);
			courseDate.setLabId(labReservation.getClassRoomId());
			courseDate.setClassRoomId("N/A");
			courseDate.setCreateBy(labReservation.getCreateBy());
			courseDate.setCourseName(labReservation.getExperimentalProject());
			courseDate.setClassNo(labReservation.getClassNo());
			courseDate.setNickName(SecurityUtils.getNickName());
			courseDate.setUserNum(labReservation.getReserveSeats());
			labCourseDateMapper.insertLabCourseDate(courseDate);
		}
		
	}

	/**
	 * 批量删除实验室预约
	 * 
	 * @param instanceIds
	 *            需要删除的实验室预约ID
	 * @return 结果
	 */
	@Override
	@Transactional
	public int deleteLabReservationByIds(Long[] instanceIds) {
		for (Long instrumentationId : instanceIds) {
			labFileService.deleteLabFile(instrumentationId, belongType);
		}
		labFlowInstanceService.deleteLabFlowInstanceByIds(instanceIds);
		// 删除预约人员及参与人员
		labReservationParameterPersonnelService.deleteLabReservationParameterPersonnelByLabReservationId(instanceIds);
		return labReservationMapper.deleteLabReservationByIds(instanceIds);
	}

	/**
	 * 删除实验室预约信息
	 * 
	 * @param instanceId
	 *            实验室预约ID
	 * @return 结果
	 */
	@Override
	@Transactional
	public int deleteLabReservationById(Long instanceId) {
		labFileService.deleteLabFile(instanceId, belongType);
		// labReservationParameterPersonnelService.deleteLabReservationParameterPersonnelByLabReservationId(instanceId);
		return labReservationMapper.deleteLabReservationById(instanceId);
	}

	@Override
	public int commitLabReservation(LabReservation labReservation) {
		labFlowInstanceService.updateLabFlowInstance(labReservation);
		labReservationMapper.updateLabReservation(labReservation);
		return labFlowInstanceService.commitFlow(labReservation);
	}

	@Override
	public List<LabFile> getInstanceFiles(Long instanceId) {
		return labFileService.getFiles(instanceId, belongType);
	}

	/**
	 * 判断某个值是否在某个区间内(区间闭合,包含所在的起始值和结束值)
	 * 
	 * @param current
	 *            特定数值
	 * @param min
	 *            区间起始位
	 * @param max
	 *            区间结束位
	 * @return true 在;false 不在
	 */
	public boolean rangeInDefined(int current, int min, int max) {
		return Math.max(min, current) == Math.min(current, max);
	}

	public List<LabReservation> queryLabReservationBlackList(LabReservation labReservation) {
		return labReservationMapper.queryLabReservationBlackList(labReservation);
	}

	@Override
	public List<LabReservation> selectReservationList(QueryEntity queryEntity) {
		SysUser loginUser = SecurityUtils.getLoginUser().getUser();
		queryEntity.setCreateBy(loginUser.getUserName());
		if (ObjectUtil.isNotNull(queryEntity.getType())) {
			if (queryEntity.getType() == 0) {
				queryEntity.setFlowStatusOpt("committed");
			} else {
				queryEntity.setFlowStatusOpt("finished");
			}
		}
		return labReservationMapper.selectReservationList(queryEntity);
	}

}
